using net_work.Common.Request;
using net_work.Common.Result;
using net_work.Data.DTO.Cou;
using net_work.Data.Entity.Cou;
using net_work.Data.Enum.Cou;
using net_work.Data.VO.Cou;
using net_work.IRepository.Cou;
using net_work.IRepository.Sys;
using net_work.IRepository.System;
using net_work.IService.Cou;
using net_work.IService.ISystem;

namespace net_work.Service.Cou;

public class TeachingService(
    ITransactionManager transactionManager,
    ITeachingRepository teachingRepository,
    ITeacherRepository teacherRepository,
    ICourseRepository courseRepository,
    ITeacherTeachingRepository teacherTeachingRepository,
    IScheduleRepository scheduleRepository,
    IExcelExportService excelExportService)
    : ITeachingService
{
    public async Task<PagedResult<TeachingResult>> GetTeachingsPagedAsync(PagedRequest request)
    {
        return await teachingRepository.GetTeachingPagedAsync(request);
    }


    public Task<Teaching?> SelectByIdAsync(long teachingId)
    {
        return teachingRepository.GetByIdAsync(teachingId);
    }

    public async Task<long> InsertTeaching(TeachingAddRequest teachingAddRequest)
    {
        var course = await courseRepository.GetByIdAsync(teachingAddRequest.CourseId);
        if (course == null)
        {
            return -1;
        }

        var validateByList = await teacherRepository.ValidateByList(teachingAddRequest.TeacherIdList);
        if (!validateByList)
        {
            return -1;
        }

        try
        {
            await transactionManager.BeginTransactionAsync();

            var teachingId = await teachingRepository.InsertAsync(teachingAddRequest);
            if (teachingId <= 0)
            {
                throw new Exception("插入失败");
            }

            foreach (var teacherId in teachingAddRequest.TeacherIdList)
            {
                var tt = await teacherTeachingRepository.InsertAsync(new TeacherTeachingAddRequest
                {
                    TeacherId = teacherId,
                    TeachId = teachingId
                });
                if (tt <= 0)
                {
                    throw new Exception("插入失败");
                }
            }

            foreach (var scheduleInfo in teachingAddRequest.ScheduleInfoList)
            {
                var s = await scheduleRepository.InsertAsync(new ScheduleAddRequest()
                {
                    TeachId = teachingId,
                    WeekDay = scheduleInfo.WeekDay,
                    ClassNumbers = scheduleInfo.ClassNumbers
                });
                if (s <= 0)
                {
                    throw new Exception("插入失败");
                }
            }

            await transactionManager.CommitTransactionAsync();
            return teachingId;
        }
        catch (Exception e)
        {
            await transactionManager.RollbackTransactionAsync();
            return -1;
        }
    }

    public async Task<int> UpdateTeaching(TeachingUpdateRequest teachingUpdateRequest)
    {
        if (teachingUpdateRequest.Id <= 0)
        {
            return -1;
        }

        var course = await courseRepository.GetByIdAsync(teachingUpdateRequest.CourseId);
        if (course == null)
        {
            return -1;
        }

        var teaching = await teachingRepository.GetByIdAsync(teachingUpdateRequest.Id);
        if (teaching is { TeachStatus: TeachStatus.Release })
        {
            return -1;
        }

        var validateByList = await teacherRepository.ValidateByList(teachingUpdateRequest.TeacherIdList);
        if (!validateByList)
        {
            return -1;
        }

        var teacherTeachingPagedResult = await teacherTeachingRepository.GetPagedAsync(new PagedRequest(1,
            PageSizeEnum.Unlimited,
            [new FilterCondition("TeachId", FilterOperator.Equals, teachingUpdateRequest.Id)]));
        var existingTeacherIds = teacherTeachingPagedResult.Data.Select(x => x.TeacherId).ToList();

        // 比对教师ID列表，找到需要删除和插入的部分
        var idsToRemove = existingTeacherIds.Except(teachingUpdateRequest.TeacherIdList).ToList();
        var idsToAdd = teachingUpdateRequest.TeacherIdList.Except(existingTeacherIds).ToList();

        var schedulePagedResult = await scheduleRepository.GetPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited,
            [new FilterCondition("TeachId", FilterOperator.Equals, teachingUpdateRequest.Id)]));
        var existingSchedules = schedulePagedResult.Data;

        // 比对课程安排表
        var schedulesToRemove = existingSchedules.Where(es =>
            !teachingUpdateRequest.ScheduleInfoList.Any(ns =>
                ns.WeekDay == es.WeekDay && ns.ClassNumbers.All(cn => es.ClassNumbers.Contains(cn)))).ToList();

        var schedulesToAdd = teachingUpdateRequest.ScheduleInfoList.Where(ns =>
            !existingSchedules.Any(es =>
                ns.WeekDay == es.WeekDay && ns.ClassNumbers.All(cn => es.ClassNumbers.Contains(cn)))).ToList();

        try
        {
            await transactionManager.BeginTransactionAsync();

            // 删除多余的教师记录
            if (idsToRemove.Count != 0)
            {
                if (!await teacherTeachingRepository.DeleteByIdsAsync(idsToRemove))
                {
                    throw new Exception("删除多余的教师记录失败");
                }
            }

            // 插入新的教师记录
            if (idsToAdd.Count != 0)
            {
                foreach (var id in idsToAdd)
                {
                    if (await teacherTeachingRepository.InsertAsync(new TeacherTeachingAddRequest()
                        {
                            TeachId = teachingUpdateRequest.Id,
                            TeacherId = id
                        }) <= 0)
                    {
                        throw new Exception("插入新的教师记录失败");
                    }
                }
            }

            // 删除多余的课程安排
            if (schedulesToRemove.Count != 0)
            {
                if (!await scheduleRepository.DeleteByIdsAsync(schedulesToRemove.Select(x => x.Id).ToList()))
                {
                    throw new Exception("删除多余的课程安排失败");
                }
            }

            // 插入新的课程安排
            if (schedulesToAdd.Count != 0)
            {
                foreach (var scheduleInfo in schedulesToAdd)
                {
                    if (await scheduleRepository.InsertAsync(new ScheduleAddRequest()
                        {
                            TeachId = teachingUpdateRequest.Id,
                            WeekDay = scheduleInfo.WeekDay,
                            ClassNumbers = scheduleInfo.ClassNumbers
                        }) <= 0)
                    {
                        throw new Exception("插入新的课程安排失败");
                    }
                }
            }

            if (!await teachingRepository.UpdateAsync(teachingUpdateRequest))
            {
                throw new Exception("更新失败");
            }

            await transactionManager.CommitTransactionAsync();
            return 1;
        }
        catch (Exception e)
        {
            await transactionManager.RollbackTransactionAsync();
            return -1;
        }
    }

    public async Task<int> DeleteTeachingByIds(List<long> ids)
    {
        return await teachingRepository.DeleteByIdsAsync(ids) ? 1 : -1;
    }

    public async Task<int> Release(long teachingId)
    {
        var pagedResult1 = await teacherTeachingRepository.GetPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited,
            [new FilterCondition("TeachId", FilterOperator.Equals, teachingId)]));
        if (pagedResult1.TotalRecords <= 0)
        {
            return -1;
        }

        var pagedResult2 = await scheduleRepository.GetPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited,
            [new FilterCondition("TeachId", FilterOperator.Equals, teachingId)]));
        if (pagedResult2.TotalRecords <= 0)
        {
            return -1;
        }

        return await teachingRepository.Release(teachingId) ? 1 : -1;
    }

    public async Task<byte[]> ExportTeaching()
    {
        var pagedAsync =
            await teachingRepository.GetTeachingPagedAsync(new PagedRequest(1, PageSizeEnum.Unlimited, null));
        return excelExportService.ExportToExcel(pagedAsync.Data);
    }
}